#pragma once

#include "../userwm.h"
#include "../winsys.h"
#include "../patterns.h"

#include <string>
#include <vector>
#include <map>


typedef std::string BinaryData;

/// Project related

/**
 * Class for various files in project. Files are linked by linker. Each file
 * can be edited seperately. File consists of 2 parts:
 *  - Name : file path. Used for referencing files.
 *  - Extension : file type.
 */
class Item : public IRefCounted, public IObservable {
public:
	Item();
	~Item();

	Item(const Item& rhs);

	int RegisterListener(CWindow* target);
	int UnregisterListener(CWindow* target);

	std::string GetName() const;
	std::string GetExtension() const;
	const BinaryData& GetData() const;

	void SetName(const std::string& newname);
	void SetData(const BinaryData& newdata);

	int RevisionNum() const;

	Project* GetOwner();
	void SetOwner(Project*);

private:
	std::string m_Name;
	BinaryData m_Content;
	int RevisionCount;

	Project* m_Owner;
};



class Project {
public:
	typedef std::map<std::string, Item*>::iterator ItemIter;

	Project();
	~Project();

	// for creating/getting item.
	Item* CreateItem(const std::string& name);
	Item* GetItem(const std::string& name);

	// for listing items.
	Item* GetFirstItem(ItemIter &iter, const std::string& name);
	Item* GetNextItem(ItemIter &iter, const std::string& name);

private:
	// Don't change this to unordered_map or something. Ordered map are required.
	std::map<std::string, Item*> Item;
};



////// Editor related

/// Class for windows editing items.
class Editor : public CWindow, public IObserver {
	friend class Item;

public:
	Editor();
	virtual ~Editor();

protected:
	bool ListenItemUpdate(Item* target);
	bool UnlistenItemUpdate(Item* target);

private:
	std::vector<Item*> m_ListeningItems;
};


class EditorFactory {
public:
	EditorFactory();
	virtual ~EditorFactory();

	virtual CWindow* CreateEditor(Item* item);
};

void RegisterFactory(const std::string& extension, EditorFactory factory);
EditorFactory* GetFactory(const std::string& extension);
